namespace Game {
    using UnityEngine;
    using System;
    using System.Collections.Generic;

    /// <summary>
	///		Tool for converting string into given type.
	///		Supported:
	///			int/long	0
	///			uint/ulong	0
	///			bool		0|1|true|false
	///			char/byte	a
	///			string		This\tIs A test\n
    ///			string[]    safadf|asdfasdf
	///			float		0.0
	///			double		0.0
	///			int[]/List<int>			1,2,3
	///			float[]/List<float>		1.1,0,2.34
	///			Vector2		1,2
	///			Vector3		1,2,3
	///			Color		R,G,B,A		【注】R,G,B,A 取值 [0-255]
	///			int[][]		1,3;12;1,3,4
	///			float[][]	1.02,3.0;1.3;
	/// </summary>
	public static class Parser {

        /// <summary>
        ///		Convert string into given type.
        /// </summary>
        /// <typeparam name="T">Type to convert into.</typeparam>
        /// <param name="data">String contains value.</param>
        /// <returns>Data.</returns>
        public static T As<T>(string data) {
            return (T)As(data, typeof(T));
        }

        /// <summary>
        ///		Convert string into object.
        /// </summary>
        /// <param name="data">String contains value.</param>
        /// <param name="type">Target type.</param>
        /// <returns>Value</returns>
        public static object As(string data, Type type) {
            if (type == typeof(string)) {
                return data;
            } else if (type == typeof(int[])) {
                List<int> ret = new List<int>();
                string[] vals = data.Split(new char[] { ',', '[', ']' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < vals.Length; ++i) ret.Add(int.Parse(vals[i]));
                return ret.ToArray();
            } else if (type == typeof(List<int>)) {
                List<int> ret = new List<int>();
                string[] vals = data.Split(new char[] { ',', '[', ']' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < vals.Length; ++i) ret.Add(int.Parse(vals[i]));
                return ret;
            } else if (type == typeof(float[])) {
                List<float> ret = new List<float>();
                string[] vals = data.Split(new char[] { ',', '[', ']' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < vals.Length; ++i) ret.Add(float.Parse(vals[i]));
                return ret.ToArray();
            } else if (type == typeof(List<float>)) {
                List<float> ret = new List<float>();
                string[] vals = data.Split(new char[] { ',', '[', ']' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < vals.Length; ++i) ret.Add(float.Parse(vals[i]));
                return ret;
            } else if (type == typeof(int[][])) {
                List<int[]> ret = new List<int[]>();
                string[] main = data.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < main.Length; ++i) {
                    string[] sub = main[i].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    List<int> one = new List<int>();
                    for (int j = 0; j < sub.Length; ++j) one.Add(int.Parse(sub[j]));
                    ret.Add(one.ToArray());
                }

                return ret.ToArray();
            } else if (type == typeof(List<int[]>)) {
                List<int[]> ret = new List<int[]>();
                string[] main = data.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < main.Length; ++i) {
                    string[] sub = main[i].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    List<int> one = new List<int>();
                    for (int j = 0; j < sub.Length; ++j) one.Add(int.Parse(sub[j]));
                    ret.Add(one.ToArray());
                }

                return ret;
            } else if (type == typeof(float[][])) {
                List<float[]> ret = new List<float[]>();
                string[] main = data.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < main.Length; ++i) {
                    string[] sub = main[i].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    List<float> one = new List<float>();
                    for (int j = 0; j < sub.Length; ++j) one.Add(float.Parse(sub[j]));
                    ret.Add(one.ToArray());
                }

                return ret.ToArray();
            } else if (type == typeof(List<float[]>)) {
                List<float[]> ret = new List<float[]>();
                string[] main = data.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < main.Length; ++i) {
                    string[] sub = main[i].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    List<float> one = new List<float>();
                    for (int j = 0; j < sub.Length; ++j) one.Add(float.Parse(sub[j]));
                    ret.Add(one.ToArray());
                }

                return ret;
            } else if (type == typeof(Color)) {
                List<int> ret = new List<int>();
                data = data.Replace(";", "");
                string[] vals = data.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < vals.Length; ++i) ret.Add(int.Parse(vals[i]));
                if (ret.Count < 3) throw new Exception("Bad format!!!");

                Color color = new Color();
                color.r = ret[0] * 1.0f / 255;
                color.g = ret[1] * 1.0f / 255;
                color.b = ret[2] * 1.0f / 255;
                color.a = ret.Count >= 4 ? (ret[3] * 1.0f / 255) : 1;

                return color;
            } else if (type == typeof(Vector2)) {
                List<float> ret = new List<float>();
                string[] vals = data.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < vals.Length; ++i) ret.Add(float.Parse(vals[i]));
                if (ret.Count < 2) throw new Exception("Bad format!!!");

                return new Vector2(ret[0], ret[1]);
            } else if (type == typeof(Vector3)) {
                List<float> ret = new List<float>();
                string[] vals = data.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                for (int i = 0; i < vals.Length; ++i) ret.Add(float.Parse(vals[i]));
                if (ret.Count < 3) throw new Exception("Bad format!!!");

                return new Vector3(ret[0], ret[1], ret[2]);
            } else if (type == typeof(bool)) {
                return !(string.IsNullOrEmpty(data) || data == "0" || data.ToLower() == "false");
            } else if (type == typeof(char) || type == typeof(byte)
                || type == typeof(int) || type == typeof(long) || type == typeof(uint) || type == typeof(ulong)
                || type == typeof(float) || type == typeof(double)) {
                return Convert.ChangeType(data, type);
            } else if (type == typeof(string[])) {
                return data.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            } else if (type.IsEnum) {
                return int.Parse(data);
            } else {
                throw new Exception("Type NOT supported!!!");
            }
        }
    }
}
